/**
 * Server-side fetch() API Fixture System
 *
 * This module monkey-patches the global fetch() function to record and replay HTTP responses
 * for server-side API calls made by Express controllers. It enables deterministic testing
 * without requiring live API credentials or network access.
 *
 * How it works:
 * - RECORD MODE (API_MODE=record): Intercepts fetch() calls, executes them normally, and saves
 *   JSON responses to test/fixtures/ using sanitized URL-based filenames.
 * - REPLAY MODE (API_MODE=replay): Intercepts fetch() calls and returns saved fixtures instead
 *   of making real network requests. Falls back to real fetch if fixture is missing (unless
 *   API_STRICT_REPLAY=1, which blocks all non-fixture requests).
 *
 * Installation: This module is automatically installed in test/tools/start-with-memory-db.js
 * before the Express app loads, ensuring all server-side fetch calls are intercepted.
 *
 * Fixture keys: Generated by keyFor() helper, which sanitizes URLs (strips sensitive query
 * params like apikey/token) and adds body hashes for POST requests to ensure uniqueness.
 *
 * See also: server-axios-fixtures.js (same pattern for axios), fixture-helpers.js (shared utilities)
 */

const fs = require('fs');
const path = require('path');
const { keyFor } = require('./fixture-helpers');

const FIXTURES_DIR = path.resolve(__dirname, '..', 'fixtures');

function installServerApiFixtures({ mode = process.env.API_MODE } = {}) {
  const strict = process.env.API_STRICT_REPLAY === '1';

  const origFetch = globalThis.fetch;

  if (mode === 'record') {
    globalThis.fetch = async (input, init = {}) => {
      const res = await origFetch(input, init);
      try {
        const url = typeof input === 'string' ? input : input.url;
        const method = (init.method || 'GET').toUpperCase();
        const ct = (res.headers.get('content-type') || '').toLowerCase();
        if (ct.includes('application/json')) {
          const body = await res.clone().text();
          const file = path.join(FIXTURES_DIR, keyFor(method, url, init.body));
          fs.writeFileSync(file, body, 'utf8');
        }
      } catch {}
      return res;
    };
    return;
  }

  if (mode === 'replay') {
    globalThis.fetch = async (input, init = {}) => {
      try {
        const url = typeof input === 'string' ? input : input.url;
        const method = (init.method || 'GET').toUpperCase();
        const file = path.join(FIXTURES_DIR, keyFor(method, url, init.body));
        if (fs.existsSync(file)) {
          const body = fs.readFileSync(file, 'utf8');
          console.log(`[fixtures] server replay ${method} ${url}`);
          return new Response(body, {
            status: 200,
            headers: { 'content-type': 'application/json; charset=utf-8' },
          });
        }
        if (strict) {
          console.warn(`[fixtures] server strict-replay missing: ${method} ${url} — blocking network`);
          throw new Error(`Strict replay: missing fixture for ${method} ${url}`);
        }
      } catch {}
      return origFetch(input, init);
    };
  }
}

module.exports = { installServerApiFixtures };
